package com.lekang.service.impl;

import com.lekang.common.core.domain.entity.SysUser;
import com.lekang.domain.Room;
import com.lekang.dto.BedDTO;
import com.lekang.mapper.BedMapper;
import com.lekang.domain.Bed;
import com.lekang.mapper.RoomMapper;
import com.lekang.service.ICaregiverBedService;
import com.lekang.service.IBedService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;

/**
 * 床位Service业务层
 * @author wjy
 * @date 2025-10-18
 */
@Service
public class BedServiceImpl implements IBedService {
    @Autowired
    private BedMapper bedMapper;

    @Autowired
    private ICaregiverBedService caregiverBedService;

    @Autowired
    private RoomMapper roomMapper;

    @Override
    public Bed selectBedById(Long id) {
        return bedMapper.selectBedById(id);
    }

    @Override
    public List<Bed> selectBedList(Bed bed) {
        return bedMapper.selectBedList(bed);
    }

    @Override
    public List<BedDTO> getBedWithAllRelations(BedDTO bedDTO) {
        List<BedDTO> bedDTOs = bedMapper.selectBedDTOList(bedDTO);
        for (BedDTO dto : bedDTOs) {
            if (dto != null) {
                List<SysUser> caregivers = caregiverBedService.getBoundCaregivers(dto.getBedId());
                dto.setCaregivers(caregivers);
            }
        }
        return bedDTOs;
    }

    @Override
    @Transactional
    public int insertBed(Bed bed) {
        // 1. 校验：同房间床位号唯一
        int bedCount = bedMapper.countByRoomAndBedNo(bed.getRoomId(), bed.getBedNo());
        if (bedCount > 0) {
            throw new RuntimeException("当前房间下床位号已存在");
        }
        // 2. 校验：房间床位是否已满
        Room room = roomMapper.selectRoomById(bed.getRoomId());
        if (room == null) {
            throw new RuntimeException("房间不存在");
        }
        // 统计房间内当前的床位总数（包括空闲和已入住的）
        Integer currentBedCount = bedMapper.countTotalByRoomId(bed.getRoomId());
        currentBedCount = (currentBedCount == null) ? 0 : currentBedCount;
        Long totalBeds = (room.getTotalBeds() == null) ? 0L : room.getTotalBeds();
        
        if (currentBedCount >= totalBeds.intValue()) {
            throw new RuntimeException("房间床位已满（" + currentBedCount + "/" + totalBeds + "），无法新增床位");
        }
        // 3. 新增床位：默认状态为「空闲」（status=0）
        bed.setStatus(0L);
        // 4. 逻辑删除默认值：未删除（0）
        if (bed.getIsDeleted() == null) {
            bed.setIsDeleted(0L);
        }
        return bedMapper.insertBed(bed);
    }

    @Override
    public int updateBed(Bed bed) {
        return bedMapper.updateBed(bed);
    }

    @Override
    public int deleteBedByIds(Long[] ids) {
        return bedMapper.deleteBedByIds(ids);
    }

    @Override
    public int deleteBedById(Long id) {
        return bedMapper.deleteBedById(id);
    }

    @Override
    public List<Long> selectBedIdsByRoomId(Long roomId) {

        return bedMapper.selectBedIdsByRoomId(roomId);
    }

    @Override
    @Transactional
    public void checkIn(Long bedId) {
// 1. 校验：床位存在且为「空闲」
        Bed bed = bedMapper.selectBedById(bedId);
        if (bed == null) throw new RuntimeException("床位不存在");
        if (bed.getStatus() != 0) throw new RuntimeException("该床位非空闲状态，无法办理入住");
        // 2. 更新床位状态为「已入住」（status=1）
        bedMapper.updateStatus(bedId, 1);
        // 3. 更新房间的「入住床位数」和「入住率」
        updateRoomOccupancy(bed.getRoomId(), 1);
    }


    @Override
    public void askForLeave(Long bedId) {
        // 1. 校验床位存在
        Bed bed = bedMapper.selectBedById(bedId);
        if (bed == null) {
            throw new RuntimeException("床位不存在");
        }
        // 2. 校验当前状态为「已入住」（status=1）
        if (bed.getStatus() != 1) {
            throw new RuntimeException("该床位非已入住状态（当前状态：" + bed.getStatus() + "），无法办理请假");
        }
        // 3. 更新床位状态为「请假中」（status=2）
        bedMapper.updateStatus(bedId, 2);
    }

    @Override
    @Transactional
    public void cancelLeave(Long bedId) {
// 1. 校验：床位存在且为「请假中」
        Bed bed = bedMapper.selectBedById(bedId);
        if (bed == null) throw new RuntimeException("床位不存在");
        if (bed.getStatus() != 2) throw new RuntimeException("该床位非请假中状态，无法办理销假");
        // 2. 更新床位状态为「已入住」（status=1）
        bedMapper.updateStatus(bedId, 1);
    }

    /**
     * 私有方法：更新房间的入住床位数和入住率
     * @param roomId 房间ID
     * @param change 变化量（+1=新增入住，-1=减少入住）
     */
    private void updateRoomOccupancy(Long roomId, int change) {
        // 1. 查询房间信息
        Room room = roomMapper.selectRoomById(roomId);
        if (room == null) {
            throw new RuntimeException("房间不存在（ID：" + roomId + "）");
        }
        // 2. 计算新的入住床位数（注意：room.getOccupiedBeds()是Long类型，需转换为int计算）
        int currentOccupied = room.getOccupiedBeds().intValue();
        int newOccupied = currentOccupied + change;
        // 校验：入住数不能为负数
        if (newOccupied < 0) {
            throw new RuntimeException("房间入住数不能为负数");
        }
        // 3. 计算入住率（保留2位小数，总床位数为Long类型，需转换为int）
        int totalBeds = room.getTotalBeds().intValue();
        BigDecimal occupancyRate;
        if (totalBeds == 0) {
            occupancyRate = BigDecimal.ZERO; // 总床位数为0时，入住率为0
        } else {
            occupancyRate = new BigDecimal(newOccupied)
                    .divide(new BigDecimal(totalBeds), 2, BigDecimal.ROUND_HALF_UP)
                    .multiply(new BigDecimal(100)); // 转换为百分比
        }
        // 4. 更新房间信息
        room.setOccupiedBeds((long) newOccupied); // 转回Long类型
        room.setOccupancyRate(occupancyRate);
        roomMapper.updateRoom(room);
    }

}